package org.ouwa.lms.client;

import org.ouwa.lms.client.manager.ManagerRegistry;
import org.ouwa.lms.client.manager.SimpleManagerRegistry;
import org.ouwa.lms.client.manager.service.DefaultRemoteServiceManager;
import org.ouwa.lms.client.manager.service.RemoteServiceManager;
import org.ouwa.lms.client.manager.ui.DefaultUIManager;
import org.ouwa.lms.client.manager.ui.UIManager;
import org.ouwa.lms.client.model.Account;
import org.ouwa.lms.client.model.Authentication;
import org.ouwa.lms.client.support.async.MyAsyncCallback;
import org.ouwa.lms.client.support.event.ApplicationEvent;
import org.ouwa.lms.client.support.event.ApplicationEventListener;
import org.ouwa.lms.client.support.widget.GooglelikeProgressIndicator;
import org.ouwa.lms.client.support.widget.ProgressIndicator;
import org.ouwa.lms.client.ui.event.LoginEvent;
import org.ouwa.lms.client.ui.event.LogoutEvent;
import org.ouwa.lms.client.ui.login.LoginPane;
import org.ouwa.lms.client.ui.student.StudentMain;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SimplePanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class OUWA_LMS implements EntryPoint {
	private static final int[] POPUP_POS = {Window.getClientWidth()/2 - 40, 0};
	
	private ManagerRegistry managerRegistry;
	private SimplePanel mainPanel;
	private LoginPane loginPane;
	private StudentMain studentMain;
	
	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		UIManager uiManager = new DefaultUIManager(false);
		RemoteServiceManager serviceManager = new DefaultRemoteServiceManager();
		managerRegistry = new SimpleManagerRegistry(uiManager, serviceManager);
		
		loginPane = new LoginPane(managerRegistry);
		loginPane.addListener(new LoginPaneListener());
		mainPanel = new SimplePanel();
		loadLogin();
		
		RootPanel.get().add(mainPanel);
	}
	
	private void loadLogin() {
		mainPanel.setWidget(loginPane);
	}
	
	private void loadStudentMain(Account account) {
		studentMain = new StudentMain(managerRegistry, account);
		studentMain.addListener(new LogoutEventListener());
		mainPanel.setWidget(studentMain);
	}
	
	/**
	 * Checks if the provided Google email has an associated account and loads correspondingly.
	 * 
	 * @param email The provided Google email
	 * @param nickname The Google account nickname
	 */
	private void login(final String email, final String nickname) {
		final ProgressIndicator progress = 
			managerRegistry.getUIManager().showProgressIndicator("Logging in...");
		((GooglelikeProgressIndicator)progress).setPopupPosition(POPUP_POS[0], POPUP_POS[1]);
		((GooglelikeProgressIndicator)progress).show();
		
		managerRegistry.getRemoteServiceManager().getRemoteAccountService().getAccount(email,
				new MyAsyncCallback<Account>() {
			@Override
			public void onSuccess(Account result) {
				if(result != null) { // load the corresponding account
					progress.hide();
					History.newItem("loggedin");
					loadStudentMain(result);
				}
				else { // create a new account
					progress.setMessage("Preparing for first use...");
					Account account = new Account(nickname, email);
					
					managerRegistry.getRemoteServiceManager().getRemoteAccountService().createAccount(account,
							new MyAsyncCallback<Account>() {
						@Override
						public void onSuccess(Account result) {
							progress.hide();
							if(result != null) { // load the corresponding account
								History.newItem("loggedin");
								loadStudentMain(result);
							}
						}
					});
				}
			}
		});
	}
	
	protected class LoginPaneListener implements ApplicationEventListener {
		@Override
		public void handle(ApplicationEvent event) {
			if(event instanceof LoginEvent) {
				String email = ((LoginEvent)event).getUsername();
				String nickname = ((LoginEvent)event).getNickname();
				boolean credentialsOkay = ((LoginEvent)event).isCredentialsOkay();
				
				if(credentialsOkay) { // this makes sure username != null
					login(email, nickname);
				}
				else { // invalid credentials
					// Do nothing
				}
			}
		}
	}
	
	protected class LogoutEventListener implements ApplicationEventListener {
		@Override
		public void handle(ApplicationEvent event) {
			if(event instanceof LogoutEvent) {
				final ProgressIndicator progress =
					managerRegistry.getUIManager().showProgressIndicator("Logging out...");
				((GooglelikeProgressIndicator)progress).setPopupPosition(POPUP_POS[0], POPUP_POS[1]);
				((GooglelikeProgressIndicator)progress).show();
				
				managerRegistry.getRemoteServiceManager().getRemoteAccountService().logout(
						new MyAsyncCallback<Authentication>() {
					@Override
					public void onSuccess(Authentication result) {
						progress.hide();
						loadLogin();
						History.newItem("loggedout");
					}
				});
			}
		}
	}
}
